/*
    libnbds
    Non-blocking Data Structures Library

    Copyright (C) 2011 Paweł Dziepak

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef NBDS_REF_PTR_H
#define NBDS_REF_PTR_H

namespace nbds {
	class ref_ptr_base {
	protected:
		void *ptr;
		int *ref_count;
	
		ref_ptr_base(void*);
		ref_ptr_base(void*, int*);

		void init(void*, int*);
		bool remove();
	};

	template<typename T>
	class ref_ptr : public ref_ptr_base {
	public:
		ref_ptr(T *ptr) :
			ref_ptr_base(reinterpret_cast<void*>(ptr)) { }
		ref_ptr(const ref_ptr<T> &rptr) :
			ref_ptr_base(rptr.ptr, rptr.ref_count) { }

		~ref_ptr() {
			if (remove())
				delete reinterpret_cast<T*>(ptr);
		}

		ref_ptr<T> &operator=(const ref_ptr<T> &a) {
			if (a.ptr != ptr) {
				if (remove())
					delete reinterpret_cast<T*>(ptr);
				init(a.ptr, a.ref_count);
			}
			return *this;	
		}

		T &operator*() {
			return *reinterpret_cast<T*>(ptr);
		}

		T *operator->() {
			return reinterpret_cast<T*>(ptr);
		}

		const T &operator*() const {
			return *reinterpret_cast<const T*>(ptr);
		}

		const T *operator->() const {
			return reinterpret_cast<const T*>(ptr);
		}
	};
}

#endif
